package com.xjoyt.pay.master.services;

import java.util.Date;

import org.apache.commons.lang.BooleanUtils;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.lang.time.DateFormatUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;

import com.xjoyt.pay.abstracts.AbstractService;
import com.xjoyt.pay.annotations.LockMethod;
import com.xjoyt.pay.annotations.LockParam;
import com.xjoyt.pay.dto.ExecuteResult;
import com.xjoyt.pay.gateway.params.CallbackParam;
import com.xjoyt.pay.gateway.params.RefundParam;
import com.xjoyt.pay.master.dto.CallbackResult;
import com.xjoyt.pay.master.dto.RefundResult;
import com.xjoyt.pay.master.po.Merchant;
import com.xjoyt.pay.master.po.Order;
import com.xjoyt.pay.master.po.Refund;
import com.xjoyt.pay.master.repository.MerchantRepository;
import com.xjoyt.pay.master.repository.OrderRepository;
import com.xjoyt.pay.master.repository.RefundRepository;

@Service
public class RefundService extends AbstractService {

	@Autowired
	private RefundRepository repository;

	@Autowired
	private MerchantRepository merchantRepository;

	@Autowired
	private OrderRepository orderRepository;

	@Autowired
	private RestTemplate restTemplate;

	@LockMethod
	public ExecuteResult<RefundResult> create(@LockParam({ "merchantId", "outTradeNo" }) RefundParam param) {
		if (StringUtils.isBlank(param.callbackUrl))
			return ExecuteResult.fail("内部回调地址不正确");
		Merchant merchant = merchantRepository.findOne(param.merchantId);
		if (merchant == null)
			return ExecuteResult.fail("商户不存在");

		if (BooleanUtils.isNotTrue(merchant.enabled))
			return ExecuteResult.fail("商户已被停用");

		if (merchant.distributor == null)
			return ExecuteResult.fail("代理商不存在");

		if (BooleanUtils.isNotTrue(merchant.distributor.enabled))
			return ExecuteResult.fail("代理商已被停用");

		if (merchant.distributor.company == null)
			return ExecuteResult.fail("机构不存在");

		if (BooleanUtils.isNotTrue(merchant.distributor.company.enabled))
			return ExecuteResult.fail("机构已被停用");

		Order order = orderRepository.findOneByMerchantIdAndOutTradeNo(param.merchantId, param.outTradeNo);
		if (order == null)
			return ExecuteResult.fail("订单不存在");

		if (BooleanUtils.isTrue(order.back))
			return ExecuteResult.fail("订单已退款，无法重复退款");
		if (order.orderConfig == null || order.orderConfig.channel == null
				|| StringUtils.isBlank(order.orderConfig.channel.refundUrl))
			return ExecuteResult.fail("此订单不支持退款");

		Long sum = repository.sumMoneyCanBackByOrderId(order.id);
		if (sum != null && (sum + param.money) > order.money)
			return ExecuteResult.fail("退款金额不能超过订单金额");

		Refund entity = new Refund();
		entity.no = DateFormatUtils.format(new Date(), "yyyyMMddHHmmssSSS");
		for (int i = 0; i < 10; i++) {
			entity.no += String.valueOf((int) (Math.random() * (10)));
		}
		entity.money = param.money;
		entity.order = order;
		entity.url = order.orderConfig.channel.refundUrl;

		entity.addedDate = new Date();
		entity.outTradeNo = param.outTradeNo;
		entity.notifyUrl = param.notifyUrl;
		entity = repository.save(entity);
		entity.callbackUrl = param.callbackUrl += entity.id;

		try {
			RefundResult result = restTemplate.postForObject(entity.url, entity, RefundResult.class);
			entity.message = StringUtils.isBlank(result.message) ? null : StringUtils.substring(result.message, 0, 255);
			if (result.success) {
				if (result.money == null)
					result.money = entity.money;
				if (StringUtils.isNotBlank(result.outTradeNo))
					entity.outTradeNo = result.outTradeNo;
				result.outTradeNo = param.outTradeNo;
				result.no = entity.no;
				entity.success = true;
				entity = repository.save(entity);
				return ExecuteResult.ok(result);
			} else {
				entity.success = false;
				entity = repository.save(entity);
				return ExecuteResult.fail(StringUtils.isBlank(result.message) ? "退款失败" : result.message);
			}
		} catch (Exception e) {
			logger.error("退款异常", e);
			e.printStackTrace();
			entity.success = false;
			entity = repository.save(entity);
			return ExecuteResult.fail("退款异常");
		}
	}

	@LockMethod
	public ExecuteResult<CallbackResult> callback(@LockParam("id") CallbackParam param) {
		Refund entity = repository.findOne(param.id);
		if (entity == null) {
			return ExecuteResult.fail("退款单不存在");
		}
		if (entity.order == null || entity.order.orderConfig == null || entity.order.orderConfig.channel == null)
			return ExecuteResult.fail("退款通道不存在");
		String url = entity.order.orderConfig.channel.refundCallbackUrl;
		if (StringUtils.isBlank(url))
			return ExecuteResult.fail("退款适配器未配置");
		try {
			CallbackResult callback = restTemplate.postForObject(url, param, CallbackResult.class);
			if (callback.success) {
				entity.doneDate = new Date();
				entity.done = true;
				if (StringUtils.isNotBlank(callback.tradeNo) && StringUtils.isBlank(entity.tradeNo)) {
					entity.tradeNo = callback.tradeNo;
				}
				repository.save(entity);
			}
			return ExecuteResult.ok(callback);
		} catch (Exception e) {
			e.printStackTrace();
			return ExecuteResult.fail("退款回调处理失败");
		}
	}

}
